#include "muxer.h"

#include <iostream>
#include <thread>
using namespace std;
extern "C"
{
#include <libavformat/avformat.h>
}

namespace lcf
{

    // 打开封装
    AVFormatContext *Muxer::Open(const char *url,
                                 AVCodecParameters *videoPara,
                                 AVCodecParameters *audioPara)
    {
        AVFormatContext *context = nullptr;
        // 创建上下文
        auto re = avformat_alloc_output_context2(&context, NULL, NULL, url);
        PrintErr(re);

        // 添加视频音频流
        if (videoPara)
        {
            auto vs = avformat_new_stream(context, NULL); // 视频流
            avcodec_parameters_copy(vs->codecpar, videoPara);
        }
        if (audioPara)
        {
            auto as = avformat_new_stream(context, NULL); // 音频流
            avcodec_parameters_copy(as->codecpar, audioPara);
        }

        // 打开IO
        re = avio_open(&context->pb, url, AVIO_FLAG_WRITE);
        PrintErr(re);
        av_dump_format(context, 0, url, 1);
        return context;
    }

    bool Muxer::WriteHead()
    {
        unique_lock<mutex> lock(mtx_);
        if (!context_)
            return false;
        // 会改变timebase
        auto re = avformat_write_header(context_, nullptr);
        PrintErr(re);
        // 打印输出上下文
        av_dump_format(context_, 0, context_->url, 1);
        beginAudioPts_ = -1;
        beginVideoPts_ = -1;

        return true;
    }

    bool Muxer::Write(AVPacket *pkt)
    {
        if (!pkt)
            return false;
        unique_lock<mutex> lock(mtx_);
        if (!context_)
            return false;
        // 没读取到pts 重构考虑通过duration 计算
        if (pkt->pts == AV_NOPTS_VALUE)
        {
            pkt->pts = 0;
            pkt->dts = 0;
        }
        if (pkt->stream_index == videoIndex_)
        {
            if (beginVideoPts_ < 0)
                beginVideoPts_ = pkt->pts;
            lock.unlock();
            RescaleTime(pkt, beginVideoPts_, srcVideoTimeBase_);
            lock.lock();
        }
        else if (pkt->stream_index == audioIndex_)
        {
            if (beginAudioPts_ < 0)
                beginAudioPts_ = pkt->pts;
            lock.unlock();
            RescaleTime(pkt, beginAudioPts_, srcAudioTimeBase_);
            lock.lock();
        }

        cout << pkt->pts << " " << flush;
        // 写入一帧数据，内部缓冲排序dts，通过pkt=null 可以写入缓冲
        auto re = av_interleaved_write_frame(context_, pkt);
        PrintErr(re);
        return true;
    }

    bool Muxer::WriteEnd()
    {
        unique_lock<mutex> lock(mtx_);
        if (!context_)
            return false;
        int re = 0;
        // auto re = av_interleaved_write_frame(c_, nullptr);//写入排序缓冲
        // PrintErr(re);
        re = av_write_trailer(context_);
        PrintErr(re);
        return true;
    }

}